<template>
  <div class="education-app">
    <McLayout class="container">
      <McHeader :title="appTitle" :logoImg="logoUrl">
        <template #operationArea>
          <div class="operations">
            <i class="icon-helping"></i>
            <button class="mini-btn" @click="newConversation">新建对话</button>
          </div>
        </template>
      </McHeader>

      <McLayoutContent v-if="startPage" style="display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px">
        <McIntroduction
          :logoImg="logoUrl"
          :title="appTitle"
          :subTitle="'欢迎使用智能答疑助手'"
          :description="introDescription"
        />
        <McPrompt :list="quickPrompts" :direction="'horizontal'" class="intro-prompt" @itemClick="handleSend($event.label)" />
      </McLayoutContent>

      <McLayoutContent class="content-container" v-else>
        <template v-for="(msg, idx) in messages" :key="idx">
          <McBubble v-if="msg.from === 'user'" :align="'right'" :avatarConfig="userAvatar">
            <McMarkdownCard :content="msg.content" />
          </McBubble>
          <McBubble v-else :avatarConfig="modelAvatar" :loading="msg.loading">
            <McMarkdownCard :content="msg.content" />
          </McBubble>
        </template>
        <div ref="messageEnd" class="h-0"></div>
      </McLayoutContent>

      <div class="shortcut" style="display:flex;align-items:center;gap:8px;padding:12px 20px;border-top:1px solid #eef2f6;background:#fff">
        <div class="api-settings" style="display:flex;gap:8px;align-items:center;margin-right:8px">
          <input class="apikey" v-model="apiKey" placeholder="API Key (optional)" />
          <input class="apikey" v-model="baseUrl" placeholder="Base URL (e.g. https://api.example.com)" />
          <input class="apikey" v-model="modelName" placeholder="Model (e.g. gpt-4o-mini)" />
        </div>
        <McPrompt v-if="!startPage" :list="simplePrompt" :direction="'horizontal'" style="flex:1" @itemClick="handleSend($event.label)" />
        <button class="add-btn" @click="newConversation">新建对话</button>
      </div>

      <McLayoutSender>
        <McInput v-model="inputValue" :placeholder="inputPlaceholder" @submit="handleSend">
          <template #extra>
            <div class="input-foot-wrapper">
              <div class="input-foot-left">
                <span v-for="(item, index) in inputFootIcons" :key="index">
                  <i :class="item.icon"></i>
                  {{ item.text }}
                </span>
                <span class="input-foot-dividing-line"></span>
                <span class="input-foot-maxlength">{{ inputValue.length }}/2000</span>
              </div>
              <div class="input-foot-right">
                <button class="clear-btn" @click="inputValue = ''">清空输入</button>
              </div>
            </div>
          </template>
        </McInput>
      </McLayoutSender>
    </McLayout>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, nextTick } from 'vue';
// import { McLayout, McHeader, McBubble, McInput, McLayoutContent, McPrompt, McMarkdownCard } from '@matechat/core';

// --- 配置常量 ---
const appTitle = '智能答疑助手 (教育场景实践)';
const inputPlaceholder = '请输入您的数学题、概念疑问或编程问题...';
const logoUrl = 'https://placehold.co/40x40/5E7CE0/ffffff?text=AI';
const userAvatar = { name: 'User', imgSrc: 'https://placehold.co/40x40/3AC295/ffffff?text=U' };
const modelAvatar = { name: 'Model', imgSrc: logoUrl };

// --- 响应式状态 ---
const inputValue = ref('');
const messages = ref<any[]>([]);
const masteryScore = ref(0.65); // 模拟初始知识掌握指数
const messageEnd = ref<HTMLElement | null>(null);

// 远程调用配置（可在 UI 中提供）
const DEFAULT_API_KEY = "";
const DEFAULT_BASE_URL = "https://api.chatanywhere.tech";
const apiKey = ref('');
const baseUrl = ref(DEFAULT_BASE_URL);
const modelName = ref('gpt-4o-mini');

const quickPrompts = ref([
  { label: '讲解牛顿第二定律', value: 'physics' },
  { label: '为什么会犯概念性错误？', value: 'diagnosis' },
  { label: '帮我检查这段Python代码', value: 'code' },
]);

// 启动页 & 简洁快捷提示
const startPage = ref(true);
const introDescription = [
  '智能答疑助手可以在数学、物理、编程等场景下给出诊断与学习建议。',
  '你可以输入题目、代码或概念问题，助手会返回诊断、解析与推荐学习路径。',
];
const simplePrompt = [
  { value: 'quickSort', iconConfig: { name: 'icon-info-o', color: '#5e7ce0' }, label: '帮我写一个快速排序' },
  { value: 'helpMd', iconConfig: { name: 'icon-star', color: 'rgb(255, 215, 0)' }, label: '你可以帮我做些什么？' },
];

const inputFootIcons = [
  { icon: 'icon-at', text: '智能体' },
  { icon: 'icon-standard', text: '词库' },
  { icon: 'icon-add', text: '附件' },
];

// --- 核心方法 ---

// 滚动到底部：优先滚动容器，否则使用 messageEnd
const scrollToBottom = () => {
  nextTick(() => {
    try {
      const container = document.querySelector('.content-container') as HTMLElement | null;
      if (container) {
        container.scrollTop = container.scrollHeight;
        return;
      }
      if (messageEnd.value) {
        messageEnd.value.scrollIntoView({ behavior: 'smooth' });
      }
    } catch (e) {
      // ignore scroll errors
    }
  });
};

// 模拟后端返回结构化数据的函数
const mockBackendResponse = (query: string) => {
  let response: any = {};
  if (query.toLowerCase().includes('python') || query.toLowerCase().includes('代码')) {
    response = {
      user_mastery_score: 0.72,
      knowledge_point: '列表推导式',
      recognized_error_type: 'calculation_error',
      detailed_explanation: `好的，我来帮你分析这段 Python 代码：

\`\`\`python
def example(n):
    return [i * 2 for i in range(n) if i % 3 == 0]
\`\`\`

**MateChat 诊断：** 你的实现逻辑没有问题，但是在大数据量下，列表推导式会占用较多内存。这属于**计算效率问题**，而非语法错误。`,
      suggested_topics: [{ name: '列表推导式 vs 生成器', link: '#generator' }],
    };
  } else if (query.toLowerCase().includes('牛顿') || query.toLowerCase().includes('力')) {
    response = {
      user_mastery_score: 0.68,
      knowledge_point: '牛顿第二定律',
      recognized_error_type: 'conceptual_mistake',
      detailed_explanation: `牛顿第二定律是经典力学的基础，其数学表达为 $F = ma$。

**MateChat 诊断：** 请注意，这里的 $F$ 必须是物体所受的**合外力**，而不是单个力。你上次提交的测试中，忽视了摩擦力的存在，导致了**概念性误区**。`,
      suggested_topics: [
        { name: '合外力的概念', link: '#netforce' },
        { name: '摩擦力与功', link: '#friction' },
      ],
    };
  } else {
    response = {
      user_mastery_score: 0.65,
      knowledge_point: '通用概念',
      recognized_error_type: 'unknown',
      detailed_explanation: `你好，我是一位 AI 答疑助手。我已为你检索相关知识点。

MateChat 实践的价值在于，通过组件化UI，将复杂的后端诊断结果（如公式、知识图谱）以标准化的 Markdown 格式呈现给用户。`,
      suggested_topics: [],
    };
  }
  return response;
};

// Markdown 空行规整工具：确保表格、分割线周围有空行，改善渲染效果
const normalizeMarkdownSpacing = (t: string) => {
  if (!t) return t;
  t = t.replace(/\n{3,}/g, '\n\n');
  t = t.replace(/\n---\n/g, '\n\n---\n\n');
  t = t.replace(/(^|\n)(\|)/g, '$1\n$2');
  t = t.replace(/\n{3,}/g, '\n\n');
  return t;
};

// 核心逻辑：MateChat 的智能交互逻辑 (fetchData)
const fetchDataForEducation = async (ques: string, modelIndex: number) => {
  if (modelIndex == null || modelIndex < 0) return;

  // 判断是否提供了 API key（UI 输入或默认）
  const used_api_key = apiKey.value && apiKey.value.trim() ? apiKey.value.trim() : DEFAULT_API_KEY;
  const used_base_url = baseUrl.value && baseUrl.value.trim() ? baseUrl.value.trim() : DEFAULT_BASE_URL;

  // 如果没有 API Key，使用本地 mock 行为（模拟流式更新）
  if (!used_api_key) {
    const data = mockBackendResponse(ques);
    masteryScore.value = data.user_mastery_score ?? masteryScore.value;
    let content = data.detailed_explanation || '';
    const error_type = data.recognized_error_type;
    const related_topics = data.suggested_topics;

    if (error_type && error_type !== 'unknown') {
      const diagnosisText = error_type === 'conceptual_mistake' ? '概念性误区' : '计算失误';
      content += `\n\n---\n**诊断：** 识别到您在 **[${data.knowledge_point}]** 存在 **${diagnosisText}**。\n`;
    }
    if (Array.isArray(related_topics) && related_topics.length > 0) {
      content += `\n**关联推荐学习路径：**\n`;
      related_topics.forEach((topic: any) => {
        content += `* [${topic.name}](${topic.link})\n`;
      });
    }

    // 规整 Markdown 空行，确保表格和分隔线被正确渲染
    content = normalizeMarkdownSpacing(content);

    // 模拟分片输出以获得流式体验
    messages.value[modelIndex].content = '';
    messages.value[modelIndex].loading = true;
    const chunks = content.match(/.{1,120}/g) || [content];
    for (const chunk of chunks) {
      await new Promise((r) => setTimeout(r, 120));
      messages.value[modelIndex].content += chunk;
      await scrollToBottom();
    }
    messages.value[modelIndex].loading = false;
    return;
  }

  // 使用远程模型（fetch + 流式解析）
  try {
    const url = used_base_url.replace(/\/+$/, '') + '/chat/completions';

    // 构建带历史的对话消息，限制历史长度以避免过长的上下文
    const maxHistory = 20;
    const startIdx = Math.max(0, messages.value.length - maxHistory);
    const historyMessages: Array<{role:string, content:string}> = [];
    // 可选 system 提示，帮助模型扮演教育助理角色
    historyMessages.push({ role: 'system', content: 'You are a helpful, concise educational assistant. Provide clear explanations, point out misconceptions, and suggest related topics.' });
    for (let i = startIdx; i < messages.value.length; i++) {
      const m = messages.value[i];
      if (!m || typeof m.content !== 'string' || !m.content.trim()) continue;
      const role = m.from === 'user' ? 'user' : 'assistant';
      historyMessages.push({ role, content: m.content });
    }
    // 添加当前用户问题
    historyMessages.push({ role: 'user', content: ques });
    const resp = await fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${used_api_key}`,
      },
      body: JSON.stringify({ model: modelName.value, messages: historyMessages, stream: true }),
    });

    if (!resp.ok) {
      const t = await resp.text();
      messages.value[modelIndex].content = `[Error] ${t}`;
      messages.value[modelIndex].loading = false;
      return;
    }

    const ct = resp.headers.get('content-type') || '';
    if (ct.includes('application/json')) {
      const data = await resp.json();
      // 如果服务器以完整 JSON 返回（非流式），也按本地 mock 一样分片追加以获得一致的流式体验
      let full = data.choices?.[0]?.message?.content || data.text || JSON.stringify(data);
      full = normalizeMarkdownSpacing(full);
      messages.value[modelIndex].content = '';
      messages.value[modelIndex].loading = true;
      const chunksFull = full.match(/.{1,120}/g) || [full];
      for (const ch of chunksFull) {
        await new Promise((r) => setTimeout(r, 120));
        messages.value[modelIndex].content += ch;
        await scrollToBottom();
      }
      messages.value[modelIndex].loading = false;
    } else if (resp.body) {
      messages.value[modelIndex].content = '';
      messages.value[modelIndex].loading = true;
      const reader = resp.body.getReader();
      const decoder = new TextDecoder();
      let buffer = '';
      while (true) {
        const { value, done } = await reader.read();
        if (done) break;
        buffer += decoder.decode(value, { stream: true });

        const lines = buffer.split(/\r?\n/);
        buffer = lines.pop() || '';

        for (const rawLine of lines) {
          const line = rawLine.trim();
          if (!line) continue;
          const dataLine = line.startsWith('data:') ? line.replace(/^data:\s*/, '') : line;
          if (dataLine === '[DONE]') continue;

          try {
            const obj = JSON.parse(dataLine);
            if (obj.id && !messages.value[modelIndex].id) messages.value[modelIndex].id = obj.id;
            const content = obj.choices?.[0]?.delta?.content ?? obj.choices?.[0]?.message?.content ?? obj.choices?.[0]?.text ?? '';
            if (content) {
              messages.value[modelIndex].content += content;
              await scrollToBottom();
            }
          } catch (e) {
            messages.value[modelIndex].content += dataLine;
            await scrollToBottom();
          }
        }
      }

      if (buffer) {
        const maybe = buffer.trim();
        if (maybe && maybe !== '[DONE]') {
          try {
            const obj = JSON.parse(maybe);
            if (obj.id && !messages.value[modelIndex].id) messages.value[modelIndex].id = obj.id;
            const content = obj.choices?.[0]?.delta?.content ?? obj.choices?.[0]?.message?.content ?? obj.choices?.[0]?.text ?? '';
            if (content) messages.value[modelIndex].content += content;
          } catch (e) {
            messages.value[modelIndex].content += maybe;
          }
        }
      }
      // 在流结束后做一次 Markdown 空行规整，修正表格/分割线渲染问题
      try {
        messages.value[modelIndex].content = normalizeMarkdownSpacing(messages.value[modelIndex].content || '');
      } catch (e) {
        // ignore normalization errors
      }
    } else {
      const text = await resp.text();
      // 非流式纯文本，按分片追加以保持体验一致（并规整 Markdown 空行）
      let finalText = text;
      finalText = normalizeMarkdownSpacing(finalText);
      messages.value[modelIndex].content = '';
      messages.value[modelIndex].loading = true;
      const chunksText = finalText.match(/.{1,120}/g) || [finalText];
      for (const ch of chunksText) {
        await new Promise((r) => setTimeout(r, 120));
        messages.value[modelIndex].content += ch;
        await scrollToBottom();
      }
      messages.value[modelIndex].loading = false;
    }
  } catch (err) {
    console.error(err);
    messages.value[modelIndex].content = '[Request failed] ' + String(err);
  } finally {
    messages.value[modelIndex].loading = false;
    await scrollToBottom();
  }
};

// 处理用户发送消息
const handleSend = (evt: string | Event | any) => {
  // 支持多种触发：字符串、事件对象或 McPrompt 的 item
  startPage.value = false;
  let text = '';
  if (typeof evt === 'string') text = evt.trim();
  else if (evt && typeof evt === 'object') {
    // McPrompt 可能传入 item 对象 { label, value }
    if (typeof evt.label === 'string') text = evt.label.trim();
    // 某些组件可能直接传入事件对象
    else if (evt.target && typeof evt.target.value === 'string') text = evt.target.value.trim();
    else text = inputValue.value.trim();
  } else {
    text = inputValue.value.trim();
  }

  if (!text) return;

  inputValue.value = '';

  // push user message (带 avatarConfig 以便显示)
  messages.value.push({ from: 'user', content: text, avatarConfig: userAvatar });

  // push placeholder for model reply and capture index
  messages.value.push({ from: 'model', content: '思考中...', loading: true, avatarConfig: modelAvatar, id: '' });
  const modelIndex = messages.value.length - 1;

  // fetch data (streaming or simulated)
  fetchDataForEducation(text, modelIndex);
};

// 新建对话：清空会话并显示欢迎消息
const newConversation = () => {
  messages.value = [];
  masteryScore.value = 0.65;
  inputValue.value = '';
  messages.value.push({
    from: 'model',
    content: '你好，我是智能答疑助手。请输入您的数学题、物理概念或编程问题，我将为您提供个性化诊断。',
    loading: false,
  });
  scrollToBottom();
};

// 初始化欢迎消息（页面加载时创建新对话）
onMounted(() => {
  newConversation();
});

// --- 样式定义 (组件内部) ---
// 为了保证在 Vue 环境中运行，我们将样式放在这里或使用外部 CSS (这里内联)
</script>

<style scoped>
.education-app {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
  background: linear-gradient(180deg, #f6f9fc, #eef6fb);
}
.container {
  width: 1000px;
  margin: 20px auto;
  height: calc(100vh - 82px);
  padding: 20px;
  gap: 8px;
  background: #fff;
  border: 1px solid #e6edf3;
  border-radius: 12px;
  display: flex;
  flex-direction: column;
}
.content-container {
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow: auto;
  padding: 16px;
}
.operations { display:flex; align-items:center; gap:8px }
.mini-btn, .add-btn, .clear-btn { background:#5e7ce0; color:#fff; border:0; padding:6px 10px; border-radius:8px; cursor:pointer }
.add-btn { margin-left:auto }
.input-foot-wrapper { display:flex; justify-content:space-between; align-items:center; width:100%; height:100%; margin-right:8px }
.input-foot-left { display:flex; align-items:center; gap:8px }
.input-foot-dividing-line { width:1px; height:14px; background:#d7d8da }
.input-foot-maxlength { font-size:13px; color:#71757f }
.input-foot-right .clear-btn { background:#f3f4f6; color:#111 }
.apikey { padding:8px 10px; border-radius:8px; border:1px dashed #c7d2fe; width:260px }
.api-settings .apikey { width:220px }
</style>